#ifndef _SPI_NOR_CMD_H_
#define	_SPI_NOR_CMD_H_

#include "stdint.h"

#ifdef __cplusplus
extern "C"
{
#endif

#define SPI_NOR_ST_DRV_POS								21		
#define SPI_NOR_ST_QE_POS								9		
#define SPI_NOR_ST_LB_POS								11		
#define SPI_NOR_ST_ADDR_MODE_POS						8		

#define SPI_NOR_ST_BUSY_MASK							0x01
#define SPI_NOR_ST_WRITE_EN								0x02	

#define SPI_NOR_CMD_Write_Enable						0x06
#define SPI_NOR_CMD_Write_Disable						0x04
#define SPI_NOR_CMD_SRWrite_Enable						0x50

#define SPI_NOR_CMD_Read_StReg1							0x05
#define SPI_NOR_CMD_Read_StReg2							0x35
#define SPI_NOR_CMD_Read_StReg3							0x15
#define SPI_NOR_CMD_Write_StReg1						0x01
#define SPI_NOR_CMD_Write_StReg2						0x31
#define SPI_NOR_CMD_Write_StReg3						0x11

#define SPI_NOR_CMD_Chip_Erase							0x60
#define SPI_NOR_CMD_Enable_Reset						0x66
#define SPI_NOR_CMD_Reset								0x99

#define SPI_NOR_CMD_Read_Identification					0x9F 
#define SPI_NOR_CMD_Read_Device_ID						0x90 

#define SPI_NOR_CMD_Read_Data							0x03 
#define SPI_NOR_CMD_Fast_Read							0x0B 

#define SPI_NOR_CMD_Quad_Read							0x6B 
#define SPI_NOR_CMD_Quad_Read_QA						0xEB 

#define SPI_NOR_CMD_Page_Program						0x02 
#define SPI_NOR_CMD_Quad_Page_Program					0x32 

#define SPI_NOR_CMD_Sector_Erase						0x20
#define SPI_NOR_CMD_Block_Erase_32K						0x52
#define SPI_NOR_CMD_Block_Erase_64K						0xD8

#define SPI_NOR_CMD_Erase_SecurityReg					0x44
#define SPI_NOR_CMD_Program_SecurityReg					0x42
#define SPI_NOR_CMD_Read_SecurityReg					0x48

#define SPI_NOR_CMD_A32_Enter_A32						0xB7
#define SPI_NOR_CMD_A32_Exit_A32						0xE9
#define SPI_NOR_CMD_A32_Set_Addr_MB						0xC5
#define SPI_NOR_CMD_A32_Get_Addr_MB						0xC8

#define SPI_NOR_CMD_A32_Sector_Erase					0x21
#define SPI_NOR_CMD_A32_Block_Erase_32K					0x5C
#define SPI_NOR_CMD_A32_Block_Erase_64K					0xDC

#define SPI_NOR_CMD_A32_Read_Data						0x13 
#define SPI_NOR_CMD_A32_Fast_Read						0x0C 
#define SPI_NOR_CMD_A32_Page_Program					0x12 

#define SPI_NOR_CMD_A32_Quad_Read						0x6C 
#define SPI_NOR_CMD_A32_Quad_Read_QA					0xEC 
#define SPI_NOR_CMD_A32_Quad_Page_Program				0x34 

#define SPI_NOR_PAGE_SIZE								0x100
#define SPI_NOR_PAGE_MASK								0xFF
#define SPI_NOR_SECTOR_SIZE								0x1000
#define SPI_NOR_BLOCK32_SIZE							0x8000
#define SPI_NOR_BLOCK64_SIZE							0x10000
#define SPI_NOR_PLANE_SIZE								0x1000000

typedef struct
{
	void(*cs)(uint8_t st);
	void(*mode_spi)(void);
	void(*mode_qpi_out)(void);
	void(*mode_qpi_in)(void);
	uint8_t(*spi_rb)(void);
	void(*spi_wb)(uint8_t dataW);
	uint8_t(*spi_write)(const uint8_t *dataw, uint32_t Len);
	uint8_t(*spi_read)(uint8_t *datar, uint32_t Len);
	uint8_t(*qpi_write)(const uint8_t *dataw, uint32_t Len);
	uint8_t(*qpi_read)(uint8_t *datar, uint32_t Len);
} multi_nor_type;

uint32_t multi_nor_init(const multi_nor_type *hal, uint8_t qspi_en);

uint8_t multi_nor_reg_get(const multi_nor_type *hal, char reg);
uint8_t multi_nor_reg_set(const multi_nor_type *hal, char reg, uint8_t msk, uint8_t val); 

uint32_t multi_nor_st_read(const multi_nor_type *hal);		
uint8_t multi_nor_busy(const multi_nor_type *hal);			
uint8_t multi_nor_wait_for_busy(const multi_nor_type *hal);	

uint8_t multi_nor_id_read(const multi_nor_type *hal, uint8_t *des);

void multi_nor_write_enable(const multi_nor_type *hal);
void multi_nor_write_disable(const multi_nor_type *hal);

uint8_t multi_nor_sector_erase(const multi_nor_type *hal, uint32_t addr);
uint8_t multi_nor_block_erase(const multi_nor_type *hal, uint32_t addr);
uint8_t multi_nor_block64_erase(const multi_nor_type *hal, uint32_t addr);
uint8_t multi_nor_chip_erase(const multi_nor_type *hal);

uint8_t multi_nor_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);		
uint8_t multi_nor_write(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);	
uint8_t multi_nor_write_multi(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

uint8_t multi_nor_q_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);	
uint8_t multi_nor_qa_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);	
uint8_t multi_nor_q_write(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);  
uint8_t multi_nor_q_write_multi(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

uint8_t multi_nor_security_reg_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);
uint8_t multi_nor_security_reg_write(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);
uint8_t multi_nor_security_reg_erase(const multi_nor_type *hal, uint32_t addr);

void multi_nor_cmd_exe(const multi_nor_type *hal, uint8_t cmd);
void multi_nor_cmd_set(const multi_nor_type *hal, uint8_t cmd, uint8_t par);
uint8_t multi_nor_cmd_get(const multi_nor_type *hal, uint8_t cmd);

uint8_t multi_nor_cmd_auto(const multi_nor_type *hal, const uint8_t *send, uint8_t send_len, uint8_t *rcv, uint8_t rcv_cnt);

uint8_t multi_nor32_enter_a32_mode(const multi_nor_type *hal);
uint8_t multi_nor32_enter_a24_mode(const multi_nor_type *hal);
uint8_t multi_nor32_addr_mb_set(const multi_nor_type *hal, uint8_t mb);
uint8_t multi_nor32_addr_mb_get(const multi_nor_type *hal);

uint8_t multi_nor32_sector_erase(const multi_nor_type *hal, uint32_t addr);
uint8_t multi_nor32_block_erase(const multi_nor_type *hal, uint32_t addr);
uint8_t multi_nor32_block64_erase(const multi_nor_type *hal, uint32_t addr);

uint8_t multi_nor32_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);		
uint8_t multi_nor32_write(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);		
uint8_t multi_nor32_write_multi(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

uint8_t multi_nor32_q_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);	
uint8_t multi_nor32_qa_read(const multi_nor_type *hal, uint32_t addr, int32_t Len, uint8_t *Des);	
uint8_t multi_nor32_q_write(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);	
uint8_t multi_nor32_q_write_multi(const multi_nor_type *hal, uint32_t addr, int32_t Len, const uint8_t *Src);

uint32_t nor_init(uint8_t qspi_en);

uint8_t nor_reg_get(char reg);
uint8_t nor_reg_set(char reg, uint8_t msk, uint8_t val);

uint32_t nor_st_read(void);			
uint8_t  nor_busy(void);			
uint8_t nor_wait_for_busy(void);	

uint8_t  nor_id_read(uint8_t *des);

void nor_write_enable(void);
void nor_write_disable(void);

uint8_t nor_sector_erase(uint32_t addr);
uint8_t nor_block_erase(uint32_t addr);
uint8_t nor_block64_erase(uint32_t addr);
uint8_t nor_chip_erase(void );

uint8_t nor_read(uint32_t addr,int32_t Len,uint8_t *Des);
uint8_t nor_write(uint32_t addr,int32_t Len,const uint8_t *Src);
uint8_t nor_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src); 

uint8_t nor_q_read(uint32_t addr,int32_t Len,uint8_t *Des);		
uint8_t nor_qa_read(uint32_t addr, int32_t Len, uint8_t *Des);		
uint8_t nor_q_write(uint32_t addr,int32_t Len, const uint8_t *Src); 		
uint8_t nor_q_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src); 

uint8_t nor_security_reg_read(uint32_t addr, int32_t Len, uint8_t *Des);
uint8_t nor_security_reg_write(uint32_t addr, int32_t Len, const uint8_t *Src);
uint8_t nor_security_reg_erase(uint32_t addr);

void nor_cmd_exe (uint8_t cmd);
void nor_cmd_set(uint8_t cmd, uint8_t par);
uint8_t nor_cmd_get(uint8_t cmd);
uint8_t nor_cmd_auto(const uint8_t *send, uint8_t send_len, uint8_t *rcv, uint8_t rcv_cnt);

uint8_t nor32_enter_a32_mode(void);
uint8_t nor32_enter_a24_mode(void);
uint8_t nor32_addr_mb_set(uint8_t mb);
uint8_t nor32_addr_mb_get(void);

uint8_t nor32_sector_erase(uint32_t addr);
uint8_t nor32_block_erase(uint32_t addr);
uint8_t nor32_block64_erase(uint32_t addr);

uint8_t nor32_read(uint32_t addr, int32_t Len, uint8_t *Des);		
uint8_t nor32_write(uint32_t addr, int32_t Len, const uint8_t *Src);		
uint8_t nor32_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src);

uint8_t nor32_q_read(uint32_t addr, int32_t Len, uint8_t *Des);		
uint8_t nor32_qa_read(uint32_t addr, int32_t Len, uint8_t *Des);	
uint8_t nor32_q_write(uint32_t addr, int32_t Len, const uint8_t *Src);	
uint8_t nor32_q_write_multi(uint32_t addr, int32_t Len, const uint8_t *Src);

#ifdef __cplusplus
}
#endif

#endif	

